﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Win32;
using System.Diagnostics;

namespace RegBrowser
{
    public partial class RegBrowserForm : Form
    {
        private List<string> _fullRegs;


        const string HKCR = "HKEY_CLASSES_ROOT";
        const string HKCU = "HKEY_CURRENT_USER";
        const string HKLM = "HKEY_LOCAL_MACHINE";
        const string HKUS = "HKEY_USERS";
        const string HKCC = "HKEY_CURRENT_CONFIG";

        public RegBrowserForm()    
        {                          
            InitializeComponent();
            InitRegs();
        }

        private void InitRegs()
        {
            lstRegs.Items.Clear();
            lstRegs.Items.Add(HKCR);
            lstRegs.Items.Add(HKCU);
            lstRegs.Items.Add(HKLM);
            lstRegs.Items.Add(HKUS);
            lstRegs.Items.Add(HKCC);
            if (_fullRegs == null)
                _fullRegs = new List<string>();
            _fullRegs.Clear();
            foreach (string oItem in lstRegs.Items)
            {
                _fullRegs.Add(oItem);
            }
            lstRegs.Items.Insert(0, "向上一级...");
        }

        private void txtFilter_TextChanged(object sender, EventArgs e)
        {
            lstRegs.Items.Clear();
            foreach (string str in _fullRegs)
            {
                if (str.ToUpper().Contains(txtFilter.Text.Trim().ToUpper()))
                {
                    lstRegs.Items.Add(str);
                }
            }
            lstRegs.Items.Insert(0, "向上一级...");
        }

        private RegistryKey GetRootRegKey(string root)
        { 
            if (root.StartsWith(HKCR))
                return Registry.ClassesRoot;
            if (root.StartsWith(HKCU))
                return Registry.CurrentUser;
            if (root.StartsWith(HKLM))
                return Registry.LocalMachine;
            if (root.StartsWith(HKUS))
                return Registry.Users;
            if (root.StartsWith(HKCC))
                return Registry.CurrentConfig;
            return null;
        }

        private RegistryKey OpenKey(string fullpath)
        {
            RegistryKey oRet = null;
            string[] subkeys = fullpath.Split('\\');
            if (subkeys.Length != 0)
            {
                oRet = GetRootRegKey(subkeys[0]);
                if (oRet != null)
                {
                    for (int i = 1; i < subkeys.Length; i++)
                    {
                        try
                        {
                            oRet = oRet.OpenSubKey(subkeys[i], true);
                        }
                        catch (Exception e)
                        {
                            MessageBox.Show(e.Message, "提示");
                        }
                        if (oRet == null)
                            break;
                    }
                }
            }
            return oRet;
        }

        private void lstRegs_DoubleClick(object sender, EventArgs e)
        {
            string strFullPath = "";
            if (lstRegs.SelectedIndex != 0)
            {
                strFullPath = txtFullPath.Text + "\\" + lstRegs.SelectedItem;
                if (strFullPath.StartsWith("\\"))
                    strFullPath = strFullPath.Substring(1, strFullPath.Length - 1);
                
            }
            else 
            {
                int nPos = txtFullPath.Text.LastIndexOf("\\");
                if (nPos < 0)
                    strFullPath = "";
                else
                    strFullPath = txtFullPath.Text.Substring(0, nPos);
            }
            txtFullPath.Text = strFullPath;
            BrowsePath(strFullPath);
        }

        private RegistryKey BrowsePath(string fullPath)
        {
            RegistryKey key = OpenKey(fullPath);
            if (key != null)
            {
                _fullRegs.Clear();
                _fullRegs.AddRange(key.GetSubKeyNames());
                lstRegs.Items.Clear();
                lstRegs.Items.AddRange(_fullRegs.ToArray());
                lstRegs.Items.Insert(0, "向上一级...");
            }
            else
            {
                InitRegs();
            }
            return key;
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            RegistryKey oKey = OpenKey(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Applets");
            if (oKey != null)
            {
                try
                {
                    oKey = oKey.OpenSubKey("Regedit", true);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "提示");
                }
                string strPath = FormatPath(txtFullPath.Text);
                oKey.SetValue("LastKey", strPath, RegistryValueKind.String);
            }
            Process[] oProcs = Process.GetProcessesByName("regedit");
            if (oProcs.Length > 0)
            {
                if (MessageBox.Show("需关闭Regedit，是否继续？", "提示", MessageBoxButtons.YesNo) == DialogResult.Yes)
                    oProcs[0].Kill();
            }
            Process.Start("regedit.exe");
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            string strFullPath = FormatPath(txtFullPath.Text);
            BrowsePath(strFullPath);
        }

        private static string FormatPath(string strFullPath)
        {
            if (strFullPath.StartsWith("\\"))
                strFullPath = strFullPath.Substring(1, strFullPath.Length - 1);
            strFullPath = RepalceRoot(strFullPath, "HKCU", "HKEY_CURRENT_USER");
            strFullPath = RepalceRoot(strFullPath, "HKLM", "HKEY_LOCAL_MACHINE");
            strFullPath = RepalceRoot(strFullPath, "HKCR", "HKEY_CLASSES_ROOT");
            return strFullPath;
        }

        private static string RepalceRoot(string fullPath, string custom, string standard)
        {
            if (fullPath.StartsWith(custom))
            {
                int nPos = fullPath.IndexOf("\\");
                fullPath = standard + fullPath.Substring(nPos, fullPath.Length - nPos);
            }
            return fullPath;
        }

        private void lstRegs_SelectedValueChanged(object sender, EventArgs e)
        {
            if (lstRegs.SelectedItem == null)
                return;
            string strFullPath = FormatPath(txtFullPath.Text);
            RegistryKey oKey = OpenKey(strFullPath);
            if (oKey != null)
            {
                try
                {
                    oKey = oKey.OpenSubKey((string)lstRegs.SelectedItem);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "提示");
                }
            }
            else
                oKey = GetRootRegKey((string)lstRegs.SelectedItem);
            if (oKey == null)
                return;
            lsvValues.Items.Clear();
            string[] sValues = oKey.GetValueNames();
            bool bHasDefaultValue = false;
            for (int i = sValues.Length - 1; i >= 0; i--)
            {
                ListViewItem oItem = new ListViewItem();
                oItem.ImageIndex = 0;
                oItem.Text = sValues[i];
                if (sValues[i] == "")
                {
                    bHasDefaultValue = true;
                    oItem.Text = "[默认]";
                }
                else
                {
                    oItem.Text = sValues[i];
                }
                oItem.SubItems.Add(oKey.GetValueKind(sValues[i]).ToString());
                oItem.SubItems.Add(oKey.GetValue(sValues[i]).ToString());
                lsvValues.Items.Add(oItem);
            }
            if (!bHasDefaultValue)
            {
                ListViewItem oDefaultItem = new ListViewItem();
                oDefaultItem.ImageIndex = 0;
                oDefaultItem.Text = "[默认]";
                oDefaultItem.SubItems.Add("String");
                oDefaultItem.SubItems.Add("");
                lsvValues.Items.Insert(0, oDefaultItem);
            }

            tslFullPath.Text = FormatPath(txtFullPath.Text + "\\" + (string)lstRegs.SelectedItem);
        }

        private void miMost_Click(object sender, EventArgs e)
        {
            if (lstRegs.SelectedIndex != 0)
            {
                string sPath = FormatPath(txtFullPath.Text + "\\" + (string)lstRegs.SelectedItem);
                if ((sPath != "") && !lstMost.Items.Contains(sPath))
                    lstMost.Items.Add(sPath);
            }
        }

        private void lstRegs_MouseDown(object sender, MouseEventArgs e)
        {
            Point pt = new Point(e.X, e.Y);
            int nIndex = lstRegs.IndexFromPoint(pt);
            if (nIndex >= 0)
            {
                lstRegs.SelectedIndex = nIndex;
            }
        }

        private void lstMost_DoubleClick(object sender, EventArgs e)
        {
            string strFullPath = FormatPath((string)lstMost.SelectedItem);
            txtFullPath.Text = strFullPath;
            BrowsePath(strFullPath);
        }

        private void RegBrowserForm_SizeChanged(object sender, EventArgs e)
        {
            pnlClient.Height = ClientSize.Height - pnlTitle.Height - slFullPath.Height;
            pnlValues.Width = ClientSize.Width - pnlNames.Width;
        }

        private void lstRegs_DrawItem(object sender, DrawItemEventArgs e)
        {
            if (e.Index >= 0)
            {
                ListBox oListBox = (ListBox)sender;
                e.DrawBackground();
                e.Graphics.DrawImage(imgRegBrowser.Images[0], new Point(0, e.Index * oListBox.ItemHeight));
                Rectangle RECT = e.Bounds;
                RECT.X += imgRegBrowser.ImageSize.Width + 3;
                e.Graphics.DrawString(oListBox.Items[e.Index].ToString(),
                    e.Font, Brushes.Black, RECT, StringFormat.GenericDefault);
            }
        }

        private void lstMost_DrawItem(object sender, DrawItemEventArgs e)
        {
            if (e.Index >= 0)
            {
                ListBox oListBox = (ListBox)sender;
                e.DrawBackground();
                e.Graphics.DrawImage(imgRegBrowser.Images[0], new Point(0, e.Index * oListBox.ItemHeight));
                Rectangle RECT = e.Bounds;
                RECT.X += imgRegBrowser.ImageSize.Width + 3;
                e.Graphics.DrawString(oListBox.Items[e.Index].ToString(),
                    e.Font, Brushes.Black, RECT, StringFormat.GenericDefault);
            }
        }

        private void lsvValues_SizeChanged(object sender, EventArgs e)
        {
            colName.Width = lsvValues.Width /3;
            colType.Width = lsvValues.Width / 6;
            colData.Width = lsvValues.Width - colName.Width - colType.Width;
        }

        private void miDeleteMost_Click(object sender, EventArgs e)
        {
            if (lstMost.SelectedItem != null)
                lstMost.Items.Remove(lstMost.SelectedItem);
        }

        private void miDelete_Click(object sender, EventArgs e)
        {
            if (lsvValues.SelectedItems.Count == 1)
            { 
                
            }
        }
    }
}
